home *** CD-ROM | disk | FTP | other *** search
/ The Original Shareware 1.1 / The Original Shareware (WeMake CDs)(Volume 1.1)(CDs, Inc)(1993).iso / 16 / col.zip / COL.C < prev    next >
C/C++ Source or Header  |  1986-01-05  |  6KB  |  222 lines

  1. /*
  2.  *  col.c -- manipulate columnar files
  3.  *
  4.  *  Columns are separated by spaces and tabs.
  5.  *  
  6.  *  Usage:
  7.  *      col [-d] "$j $k ... " [infile]
  8.  *  where j, k, etc are column numbers.  Input is from stdin if no
  9.  *  file is specified.  Output is to stdout (you can use redirection).
  10.  */
  11.  
  12. /*
  13.  *  Copyright (c) 1985 by David Dyer-Bennet
  14.  *  Permission for non-commercial use is hereby granted; all other
  15.  *  rights are reserved.
  16.  *
  17.  *  Written by David Dyer-Bennet
  18.  *  Terrabit Software
  19.  *  4242 Minnehaha Ave S
  20.  *  Minneapolis, MN 55406
  21.  *  Sysop of Fido 14/341, The Terraboard, (612) 721-8967 3/12/24 24hrs
  22.  *  (612) 721-8800 NOT 24 hrs!  More like noon to midnight
  23.  */
  24.  
  25. /*
  26.  *  Revision history:
  27.  *
  28.  *      Edit    Date        Who     Description
  29.  *
  30.  *  Version 1.0
  31.  *      1       6-Jan-86    DD-B    Initial creation
  32.  */
  33.  
  34. #include <stdio.h>
  35. #include <ctype.h>
  36.  
  37.  
  38. /* External variables */
  39. extern int errno;
  40.  
  41. /* Global variables */
  42.  
  43. int debug = 0;            /* Non-zero turns on debugging stuff */
  44.  
  45. #define MAXCOL 80        /* Max number of columns */
  46.                 /* (numbered 0 to MAXCOL-1) */
  47. int pattern [MAXCOL];        /* Columns to put out */
  48. int patcnt;            /* # of used slots in pattern [] */
  49.  
  50.  
  51. #define MAXFIELD 80        /* Max field length */
  52. char cols [MAXCOL] [MAXFIELD+1];/* Put data here after parsing */
  53.                 /* (Allow for terminating NUL in field) */
  54.  
  55. #define MAXLINE 256        /* Note this is < maxfield * maxcol */
  56. char linbuf [MAXLINE+1];    /* Buffer to read line into */
  57.                 /* (Allow for terminating '\n') */
  58.  
  59. /*  Function declarations */
  60. void usage (char *);
  61. void parse_pat (char *);
  62. void parse_line (char *);
  63.  
  64. main (ac, av)
  65. int ac;
  66. char *av[];
  67. {
  68.     FILE *ifil;
  69.     int saverr;            /* Useed to hold an error number */
  70.     int i, ax = 0;
  71.     char *ap;
  72.     
  73.     while (*av[++ax] == '-')  {    /* Process leading switches */
  74.     ap = av[ax];
  75.     while (*++ap) {        /* Multiple switches after one '-' */
  76.         switch (*ap) {
  77.         case 'd':
  78.         case 'D':
  79.             debug++;
  80.         break;
  81.         default:
  82.             usage ("Invalid switch");
  83.         break;
  84.         }            /* end switch (*ap) */
  85.     }            /* end while (*++ap) */
  86.     }                /* end while () */
  87.         
  88.     if (ac < ax+1) usage ("Not enough arguments");
  89.     
  90.     parse_pat (av[ax]);        /* Set up pattern [] */
  91.  
  92.     if (ac > ax+2) usage ("Too many arguments");
  93.     
  94.     if (ac == ax+2) {        /* If there is a file argument */
  95.     ifil = fopen (av [ax+1], "r");
  96.     if (!ifil) {
  97.         saverr = errno;
  98.         fprintf (stderr, "col: Can't open %s because\n", av [2]);
  99.         errno = saverr;    /* Cheat to make perror happy */
  100.         perror ("    ");
  101.         exit (1);
  102.     }
  103.     } else
  104.     ifil = stdin;
  105.     
  106.     while (!feof(ifil)) {
  107.     if (fgets (linbuf, MAXLINE, ifil)) {    /* If there's a line */
  108.         parse_line (linbuf);/* Break up into cols */
  109.         /* Write the columns in order given by pattern */
  110.         for (i = 0; i < patcnt; i++) {
  111.         fputs (cols [pattern [i]], stdout);
  112.         putc (' ', stdout);
  113.         }
  114.         putc ('\n', stdout);
  115.     }            /* end if (fgets ()) */
  116.     }                /* end while (!feof (ifil)) */
  117.     fclose (ifil);
  118.     exit (0);            /* All ok */
  119. }                /* end of main () */
  120.  
  121.  
  122. void usage (s)
  123. char *s;
  124. {
  125.     fprintf (stderr, "col: %s\n", s);
  126.     fprintf (stderr, "Usage:\n    col [-d] \"$j $k ...\" [infile]\n");
  127.     exit (2);
  128. }
  129.  
  130. void parse_pat (pat)
  131. char *pat;
  132. /*
  133.  *  Parse the argument into the list of columns and place in
  134.  *  pattern [].
  135.  */
  136. {
  137.     int i;
  138.  
  139.     if (debug) {
  140.     fprintf (stderr, "parse_pat (\"%s\")\n", pat);
  141.     }
  142.     
  143.     patcnt = 0;            /* Count of used slots in pattern [] */
  144.     while (*pat) {        /* As long as there is some pattern */
  145.     switch (*pat) {
  146.  
  147.         case ' ':        /* White space */
  148.         case '\t':
  149.         break;        /* Skip over it */
  150.     
  151.         case '$':        /* Beginning of column specifier */
  152.         if (patcnt >= MAXCOL) {
  153.             usage ("Too many columns");
  154.         }
  155.         i = 0;
  156.         while (isdigit(*++pat)) {
  157.             i = 10*i + *pat-'0';
  158.         }
  159.         pattern [patcnt++] = i-1;    /* User numbers from 1 */
  160.                 /* but we number from 0 */
  161.         pat--;        /* Put back our lookahead */
  162.         break;
  163.         
  164.         default:        /* Anything else is illegal */
  165.         usage ("Invalid pattern");
  166.         break;
  167.         
  168.     }            /* end switch () */
  169.     pat++;            /* On to next pattern char */
  170.     }                /* end while (*pat) */
  171.     if (debug > 1) {
  172.     fprintf (stderr, "pattern is: ");
  173.     for (i = 0; i < patcnt; i++)
  174.         fprintf (stderr, "%d ", pattern[i]);
  175.     fputc ('\n', stderr);
  176.     }
  177. }                /* end parse_pat () */
  178.  
  179. void parse_line (lp)
  180. char *lp;
  181. /*
  182.  *  Parse a line into the fields in each space-delimited column,
  183.  *  placing the results in cols [] [].
  184.  */
  185. {
  186.     int cc = 0;            /* Current/next column */
  187.     char *fp;            /* Pointer to current field */
  188.     int fcnt;            /* Count of chars in field */
  189.     
  190.     if (debug > 1) {
  191.     fprintf (stderr, "parse_line(\"%s\")\n", lp);
  192.     }
  193.     
  194.     while (*lp != '\n') {    /* As long as there's something left */
  195.     while (*lp == ' ' || *lp == '\t')
  196.         lp++;        /* Skip over white space */
  197.     if (*lp != '\n') {    /* If not at end yet */
  198.         if (cc >= MAXCOL)
  199.         usage ("Too many columns in input record");
  200.         fp = cols [cc];    /* Set up pointer to field */
  201.         fcnt = 0;        /* Init field cound */
  202.         do {        /* Pick up the field */
  203.         *fp++ = *lp++;
  204.         fcnt++;        /* Keep count, but check later */
  205.         } while (*lp != ' ' && *lp != '\t' && *lp != '\n');
  206.         *fp = '\0';        /* Make a real string */
  207.         if (fcnt >= MAXFIELD)
  208.         usage ("Maximum field length exceeded");
  209.         cc++;        /* Here's a new column */
  210.     }            /* end if (*lp != '\n') */
  211.     }                /* end while (*lp != '\n') */
  212.     while (++cc < MAXCOL) *(cols[cc]) = '\0';    /* Clear rest */
  213.     if (debug > 2) {
  214.     fprintf (stderr, "Line: ");
  215.     for (cc=0; *cols[cc]; cc++)
  216.         fprintf (stderr, "<%s> ", cols[cc]);
  217.     fputc ('\n', stderr);
  218.     }
  219. }                /* end parse_line () */
  220.  
  221. /* end of col.c */
  222.